package cn.test.learnkotlin.v1

private class HExpand {
    class User(var name: String) {

    }

    /**
     * 扩展函数
     */
    fun User.Print() {
        print("用户名:${name}")
    }

    fun fooExpand() {
        val user = User("KK")
        user.Print()
    }

    fun MutableList<Int>.swap(index1: Int, index2: Int) {
        val tmp = this[index1]
        this[index1] = this[index2]
        this[index2] = tmp
    }

    fun fooSwap() {
        val list = mutableListOf(1, 2, 3)
        println("before:${list}")
        list.swap(0, 2)
        print("after :${list}")
    }

    /**
     * 扩展函数是静态解析的
     */
    open class C
    class D : C()

    fun C.foo() = "C"
    fun D.foo() = "D"

    fun fooStaticExpand() {
        val c: C = D()
        print(c.foo())
    }

    /**
     * 若扩展函数和成员函数一致时，会优先使用成员函数
     */
    class C1 {
        fun foo() {
            println("成员函数")
        }
    }

    fun C1.foo() {
        println("扩展函数")
    }

    fun fooFunPriority() {
        C1().foo()
    }

    /**
     * 在扩展函数中判空
     */
    fun Any?.toString(): String {
        if (this == null) return "NULL"
        return toString()
    }

    /**
     * 扩展属性
     */
    val <T> List<T>.lastIndex: Int
        get() = size - 1

    /**
     * 伴生对象的扩展
     */
    class MyClass {
        companion object {
            fun foo() {
                println("foo of companion")
            }
        }

        fun foo() {
            println("foo of MyClass")
        }
    }

    fun MyClass.Companion.bar() {
        println("bar in companion")
    }

    val MyClass.Companion.no
        get() = 1

    fun fooCompanion() {
        println("MyClass's companion no:${MyClass.no}")
        MyClass.bar()
        MyClass.foo()
        MyClass().foo()
    }

    /**
     * 扩展声明为成员
     */
    open class D1 {
        fun bar() {
            println("D bar")
        }
    }

    class C2 {
        fun baz() {
            println("C baz")
        }

        fun D1.foo() {
            bar()
            baz()
        }

        fun caller() {
            D1().foo()
        }

        fun bar() {
            println("C bar")
        }

        fun D1.testPriority() {
            bar()
            this.bar()
            this@C2.bar()
        }

        fun testPriority() {
            D1().testPriority()
        }
    }

    fun fooExpandMember() {
        C2().caller()
        C2().testPriority()
    }

    /**
     * override expand
     */
    open class D3 {

    }

    class D4 : D3() {}

    open class C3 {
        open fun D3.foo() {
            println("D3 in C3")
        }

        open fun D4.foo() {
            println("D4 in C3")
        }

        fun call(d: D3) {
            d.foo()
        }
    }

    class C4 : C3() {
        override fun D3.foo() {
            println("D3 in C4")
        }

        override fun D4.foo() {
            println("D4 in C4")
        }
    }

    fun fooOverrideExpandMethod() {
        C3().call(D3())
        C3().call(D4())
        C4().call(D3())
        C4().call(D4())
    }

    /**
     * 伴生对象 扩展 补充
     */
    class MyClass2 {
        companion object {
            val cpnField1 = 1
            val cpnField2 = "this is field2"

            fun cpnFun1() {
                println("cpnFun1")

            }

        }

        fun Companion.foo() {
            println("foo inside")
        }

        init {
            MyClass2.foo()
        }
    }

    val MyClass2.Companion.no
        get() = 10

    fun MyClass2.Companion.foo() {
        println("foo outside")
    }

    fun fooCompanionPlus() {
        println("expand no: ${MyClass2.no}")
        println("field1: ${MyClass2.cpnField1}")
        println("field2: ${MyClass2.cpnField2}")
        MyClass2.foo()
        MyClass2()
    }

    fun main() {
        fooCompanionPlus()
    }
}

fun main() {
    println("-----------------------------------------------------------------------------------")
    HExpand().main()
    print("\n-----------------------------------------------------------------------------------")
}

